package com.mz.mattress.core.voice;

import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/vehicle/c4")
public class MotherboardController {

    // CRC16查表数组 (来自协议文档)
    private static final byte[] aucCRCHi = {
            (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41,
            (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40,
            (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40,
            (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41,
            (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40,
            (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41,
            (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41,
            (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40,
            (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40,
            (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41,
            (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41,
            (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40,
            (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41,
            (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40,
            (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40,
            (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41,
            (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40,
            (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41,
            (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41,
            (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40,
            (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41,
            (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40,
            (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40,
            (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41,
            (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41,
            (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40,
            (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40,
            (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41,
            (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40,
            (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41,
            (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41,
            (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40
    };

    private static final byte[] aucCRCLo = {
            (byte) 0x00, (byte) 0xC0, (byte) 0xC1, (byte) 0x01, (byte) 0xC3, (byte) 0x03, (byte) 0x02, (byte) 0xC2,
            (byte) 0xC6, (byte) 0x06, (byte) 0x07, (byte) 0xC7, (byte) 0x05, (byte) 0xC5, (byte) 0xC4, (byte) 0x04,
            (byte) 0xCC, (byte) 0x0C, (byte) 0x0D, (byte) 0xCD, (byte) 0x0F, (byte) 0xCF, (byte) 0xCE, (byte) 0x0E,
            (byte) 0x0A, (byte) 0xCA, (byte) 0xCB, (byte) 0x0B, (byte) 0xC9, (byte) 0x09, (byte) 0x08, (byte) 0xC8,
            (byte) 0xD8, (byte) 0x18, (byte) 0x19, (byte) 0xD9, (byte) 0x1B, (byte) 0xDB, (byte) 0xDA, (byte) 0x1A,
            (byte) 0x1E, (byte) 0xDE, (byte) 0xDF, (byte) 0x1F, (byte) 0xDD, (byte) 0x1D, (byte) 0x1C, (byte) 0xDC,
            (byte) 0x14, (byte) 0xD4, (byte) 0xD5, (byte) 0x15, (byte) 0xD7, (byte) 0x17, (byte) 0x16, (byte) 0xD6,
            (byte) 0xD2, (byte) 0x12, (byte) 0x13, (byte) 0xD3, (byte) 0x11, (byte) 0xD1, (byte) 0xD0, (byte) 0x10,
            (byte) 0xF0, (byte) 0x30, (byte) 0x31, (byte) 0xF1, (byte) 0x33, (byte) 0xF3, (byte) 0xF2, (byte) 0x32,
            (byte) 0x36, (byte) 0xF6, (byte) 0xF7, (byte) 0x37, (byte) 0xF5, (byte) 0x35, (byte) 0x34, (byte) 0xF4,
            (byte) 0x3C, (byte) 0xFC, (byte) 0xFD, (byte) 0x3D, (byte) 0xFF, (byte) 0x3F, (byte) 0x3E, (byte) 0xFE,
            (byte) 0xFA, (byte) 0x3A, (byte) 0x3B, (byte) 0xFB, (byte) 0x39, (byte) 0xF9, (byte) 0xF8, (byte) 0x38,
            (byte) 0x28, (byte) 0xE8, (byte) 0xE9, (byte) 0x29, (byte) 0xEB, (byte) 0x2B, (byte) 0x2A, (byte) 0xEA,
            (byte) 0xEE, (byte) 0x2E, (byte) 0x2F, (byte) 0xEF, (byte) 0x2D, (byte) 0xED, (byte) 0xEC, (byte) 0x2C,
            (byte) 0xE4, (byte) 0x24, (byte) 0x25, (byte) 0xE5, (byte) 0x27, (byte) 0xE7, (byte) 0xE6, (byte) 0x26,
            (byte) 0x22, (byte) 0xE2, (byte) 0xE3, (byte) 0x23, (byte) 0xE1, (byte) 0x21, (byte) 0x20, (byte) 0xE0,
            (byte) 0xA0, (byte) 0x60, (byte) 0x61, (byte) 0xA1, (byte) 0x63, (byte) 0xA3, (byte) 0xA2, (byte) 0x62,
            (byte) 0x66, (byte) 0xA6, (byte) 0xA7, (byte) 0x67, (byte) 0xA5, (byte) 0x65, (byte) 0x64, (byte) 0xA4,
            (byte) 0x6C, (byte) 0xAC, (byte) 0xAD, (byte) 0x6D, (byte) 0xAF, (byte) 0x6F, (byte) 0x6E, (byte) 0xAE,
            (byte) 0xAA, (byte) 0x6A, (byte) 0x6B, (byte) 0xAB, (byte) 0x69, (byte) 0xA9, (byte) 0xA8, (byte) 0x68,
            (byte) 0x78, (byte) 0xB8, (byte) 0xB9, (byte) 0x79, (byte) 0xBB, (byte) 0x7B, (byte) 0x7A, (byte) 0xBA,
            (byte) 0xBE, (byte) 0x7E, (byte) 0x7F, (byte) 0xBF, (byte) 0x7D, (byte) 0xBD, (byte) 0xBC, (byte) 0x7C,
            (byte) 0xB4, (byte) 0x74, (byte) 0x75, (byte) 0xB5, (byte) 0x77, (byte) 0xB7, (byte) 0xB6, (byte) 0x76,
            (byte) 0x72, (byte) 0xB2, (byte) 0xB3, (byte) 0x73, (byte) 0xB1, (byte) 0x71, (byte) 0x70, (byte) 0xB0,
            (byte) 0x50, (byte) 0x90, (byte) 0x91, (byte) 0x51, (byte) 0x93, (byte) 0x53, (byte) 0x52, (byte) 0x92,
            (byte) 0x96, (byte) 0x56, (byte) 0x57, (byte) 0x97, (byte) 0x55, (byte) 0x95, (byte) 0x94, (byte) 0x54,
            (byte) 0x9C, (byte) 0x5C, (byte) 0x5D, (byte) 0x9D, (byte) 0x5F, (byte) 0x9F, (byte) 0x9E, (byte) 0x5E,
            (byte) 0x5A, (byte) 0x9A, (byte) 0x9B, (byte) 0x5B, (byte) 0x99, (byte) 0x59, (byte) 0x58, (byte) 0x98,
            (byte) 0x88, (byte) 0x48, (byte) 0x49, (byte) 0x89, (byte) 0x4B, (byte) 0x8B, (byte) 0x8A, (byte) 0x4A,
            (byte) 0x4E, (byte) 0x8E, (byte) 0x8F, (byte) 0x4F, (byte) 0x8D, (byte) 0x4D, (byte) 0x4C, (byte) 0x8C,
            (byte) 0x44, (byte) 0x84, (byte) 0x85, (byte) 0x45, (byte) 0x87, (byte) 0x47, (byte) 0x46, (byte) 0x86,
            (byte) 0x82, (byte) 0x42, (byte) 0x43, (byte) 0x83, (byte) 0x41, (byte) 0x81, (byte) 0x80, (byte) 0x40
    };

    @PostMapping("/port")
    public String port(@RequestBody String message) {
        System.out.println("message:" + message);
        return null;
    }

    /**
     * 1、用E6测试LED工具，看看返回的命令和后台的命令是否一致
     * 2、如果不一致，说明可能是加密的问题
     * @param message
     * @return
     */
    @PostMapping("/motherboard")
    public String motherboard(@RequestBody String message) {
        try {
            // 构建语音播报命令 (0x22命令)
            String voiceCommand = buildVoiceCommand();

            // 构建屏幕显示命令 (0x27命令)
            String displayCommand = buildDisplayCommand();

            // 将两个命令组合（按照协议要求，命令之间需要间隔）
            String combinedCommand = voiceCommand + displayCommand;
            String sData = Base64.encode(HexStringToByte(displayCommand));
//            String sData = Base64.encode(HexStringToByte(combinedCommand));
            System.out.println("sData:" + sData);
            System.out.println("voiceCommand:" + voiceCommand);

            /*
            *
            * 一路平安 ：文本命令
            [2025-11-20 16:17:58 364] --AA55(包头) 1A(流水号) 64(地址) 00(业务类型) 27(命令) 000C(长度) 01000100D2BBC2B7C6BDB0B2(内容) 6B19(校验) AF(结束符)
            [2025-11-20 16:17:58 373]  发送 AA551A640027000C01000100D2BBC2B7C6BDB0B26B19AF
            *                              AA551E640027000C01000100D2BBC2B7C6BDB0B2EFE8AF
            *                              AA551F640027000C01000100D2BBC2B7C6BDB0B23ED5AF
            *


            [2025-11-20 16:30:26 670] --AA55(包头) 20(流水号) 64(地址) 00(业务类型) 22(命令) 0001(长度) 02(内容) 5432(校验) AF(结束符)
            [2025-11-20 16:30:26 679]  发送 AA55 20 64 00 22 0001 02 5432 AF  LED工具
            *                              AA55 00 64 00 22 0001 02 5C19 AF  我生成的
            [2025-11-20 16:30:26 684]  发送成功

            * */
            /*String cmd = "{\"Response_AlarmInfoPlate\":" +
                    "{\"info\":\"ok\"," +
                    "\"serialData\":[" +
                    "{\"serialChannel\":0," +
                    "\"data\":\"" + sData + "\"," +
                    "\"dataLen\":" + sData.length() + "}" + // dataLen是字节数，不是字符数
                    "]" +
                    "}}";*/
            String cmd = "{\"Response_AlarmInfoPlate\": " +
                    "{\"playerver_json_request\": " +
                    "{\"type\": \"ps_voice_play\"," +
                    "\"voice\":\"" + sData + "\"," +
                    "\"voice_interval\": 0," +
                    "\"voice_volume\": 100," +
                    "\"voice_male\": 1}" +
                    "}" +
                    "}";

            return cmd;

        } catch (Exception e) {
            e.printStackTrace();
            return "{\"Response_AlarmInfoPlate\":{\"info\":\"error\",\"message\":\"" + e.getMessage() + "\"}}";
        }
    }

    private static byte[] HexStringToByte(String hexString) {
        if ((hexString.length() % 2) != 0) {
            throw new IllegalArgumentException("字符长度非偶数，异常");
        }
        byte[] t = new byte[hexString.length() / 2];
        for (int i = 0; i < hexString.length(); i += 2) {
            String m = hexString.substring(i, i + 2);
            t[i / 2] = (byte) Integer.parseInt(m, 16);
        }
        return t;
    }

    /**
     * 构建语音播报命令 (0x22命令)
     * 语音"一路平安"对应的HEX值为0x02
     */
    private String buildVoiceCommand() {
        // 数据部分: 语音编号 (一路平安 = 0x02)
        byte[] data = new byte[]{(byte) 0x02};

        // 构建完整数据包 (不包括包头和结束符)
        byte[] packetData = new byte[]{
                0x00, // 流水号
                0x64, // 地址 (100)
                0x00, // 保留
                0x22, // 命令 (语音播报)
                0x00, 0x01, // 长度 (1字节)
                data[0], // 数据
                0x00, 0x00  // 校验位占位 (后面计算)
        };

        // 计算CRC16校验 (从流水号到数据结束，包括占位的00 00)
        byte[] crcData = new byte[packetData.length - 2]; // 去掉占位的校验位
        System.arraycopy(packetData, 0, crcData, 0, crcData.length);
        crcData[crcData.length - 2] = 0x00; // 填充00
        crcData[crcData.length - 1] = 0x00; // 填充00

        int crc = calculateCRC16(crcData, crcData.length);

        // 将CRC值设置到数据包中
        packetData[packetData.length - 2] = (byte) ((crc >> 8) & 0xFF); // 高字节
        packetData[packetData.length - 1] = (byte) (crc & 0xFF);        // 低字节

        // 构建完整帧 (加上包头和结束符)
        byte[] frame = new byte[packetData.length + 3]; // 包头2 + 数据 + 结束符1
        frame[0] = (byte) 0xAA; // 包头
        frame[1] = (byte) 0x55; // 包头
        System.arraycopy(packetData, 0, frame, 2, packetData.length);
        frame[frame.length - 1] = (byte) 0xAF; // 结束符

        return bytesToHex(frame);
    }

    /**
     * 构建屏幕显示命令 (0x27命令)
     * 显示"一路平安"在第一行，绿色，显示5秒
     */
    private String buildDisplayCommand() {
        try {
            // "一路平安"的GBK编码
            byte[] textBytes = "一路平安".getBytes("GBK");

            // 数据部分: 控制字1 + 控制字2 + 控制字3 + 控制字4 + 文本内容
            byte[] data = new byte[4 + textBytes.length];

            // 控制字1: 行号 (1=第一行)
            data[0] = 0x01;

            // 控制字2: 显示时长 (5秒)
            data[1] = 0x05;

            // 控制字3: 颜色 (2=绿色)
            data[2] = 0x02;

            // 控制字4: 保留
            data[3] = 0x00;

            // 文本内容
            System.arraycopy(textBytes, 0, data, 4, textBytes.length);

            // 构建完整数据包 (不包括包头和结束符)
            byte[] packetData = new byte[6 + data.length + 2]; // 流水号到数据 + 校验占位

            packetData[0] = 0x01; // 流水号 (与语音命令不同)
            packetData[1] = 0x64; // 地址 (100)
            packetData[2] = 0x00; // 保留
            packetData[3] = 0x27; // 命令 (临显指令)
            packetData[4] = 0x00; // 长度高字节
            packetData[5] = (byte) data.length; // 长度低字节

            // 数据
            System.arraycopy(data, 0, packetData, 6, data.length);

            // 校验位占位
            packetData[packetData.length - 2] = 0x00;
            packetData[packetData.length - 1] = 0x00;

            // 计算CRC16校验 (从流水号到数据结束，包括占位的00 00)
            byte[] crcData = new byte[packetData.length - 2]; // 去掉占位的校验位
            System.arraycopy(packetData, 0, crcData, 0, crcData.length);
            crcData[crcData.length - 2] = 0x00; // 填充00
            crcData[crcData.length - 1] = 0x00; // 填充00

            int crc = calculateCRC16(crcData, crcData.length);

            // 将CRC值设置到数据包中
            packetData[packetData.length - 2] = (byte) ((crc >> 8) & 0xFF); // 高字节
            packetData[packetData.length - 1] = (byte) (crc & 0xFF);        // 低字节

            // 构建完整帧 (加上包头和结束符)
            byte[] frame = new byte[packetData.length + 3]; // 包头2 + 数据 + 结束符1
            frame[0] = (byte) 0xAA; // 包头
            frame[1] = (byte) 0x55; // 包头
            System.arraycopy(packetData, 0, frame, 2, packetData.length);
            frame[frame.length - 1] = (byte) 0xAF; // 结束符

            return bytesToHex(frame);

        } catch (Exception e) {
            throw new RuntimeException("构建显示命令失败", e);
        }
    }

    /**
     * CRC16计算 (严格按照协议文档中的查表算法)
     */
    private int calculateCRC16(byte[] pucFrame, int usLen) {
        int ucCRCHi = 0xFF;
        int ucCRCLo = 0xFF;
        int iIndex;
        int i = 0;

        while (usLen-- > 0) {
            iIndex = (ucCRCLo ^ (pucFrame[i++] & 0xFF)) & 0xFF;
            ucCRCLo = (ucCRCHi ^ (aucCRCHi[iIndex] & 0xFF)) & 0xFF;
            ucCRCHi = aucCRCLo[iIndex] & 0xFF;
        }

        return ((ucCRCHi & 0xFF) << 8) | (ucCRCLo & 0xFF);
    }

    /**
     * 字节数组转十六进制字符串
     */
    private String bytesToHex(byte[] bytes) {
        StringBuilder hexString = new StringBuilder();
        for (byte b : bytes) {
            String hex = Integer.toHexString(0xFF & b);
            if (hex.length() == 1) {
                hexString.append('0');
            }
            hexString.append(hex);
        }
        return hexString.toString().toUpperCase();
    }
}